﻿package ch.sfug.anim.tween.filter {
	import ch.sfug.anim.tween.CompositeTween;	
	
	import flash.display.DisplayObject;
	import flash.events.EventDispatcher;
	import flash.filters.BitmapFilter;
	
	import ch.sfug.anim.tween.property.PropertyTween;
	import ch.sfug.events.TweenEvent;		

	/**
	 * this is a common super class for all kinds of filter tweens. it organizes the filter array of the target display object.
	 * it allows multiple filtertweens that act on the same target with the limitation that it searches for the filter class in the
	 * filter array and replaces it with the updated filter. that means if you have multiple filters of the same type, for example BlurFilter's 
	 * it will replaces all this instances with the current active BlurTween on the displayobject.
	 * but if you have a DropShadowTween and a BlurTween running it works side by side with no conflict.
	 * 
	 * 
	 * @author mich
	 */
	public class AbstractFilterTween extends CompositeTween {

		private var t:DisplayObject;

		public function AbstractFilterTween( dis:DisplayObject, d:Number ) {
			super();
			tween = new PropertyTween( null, d );
			tween.addEventListener( TweenEvent.TWEEN_UPDATE, updateFilters );
			target = dis;
			readStartFilter();
		}
		
		
		protected function readStartFilter():void {
			for each( var f:BitmapFilter in target.filters ) {
				if( f is getClass() ) {
					filter = f;
					break;
				}
			}
			if( filter == null ) filter = defaultFilter();
		}

		
		protected function updateFilters( event:TweenEvent = null ):void {
			
			var filters:Array = target.filters.slice();
			var replaced:Boolean = false;
			
			for( var i:Number = 0; i < filters.length; i++ ) {
				var f:BitmapFilter = BitmapFilter( filters[ i ] );
				if( f is getClass() ) {
					
					replaced = true;
					if( shouldBeApplied() ) {
						filters.splice( i, 1, filter );
					} else {
						filters.splice( i, 1 );
					}
				}
			}
			// if no filter was found add my filter
			if( !replaced ) filters.push( filter );
			t.filters = filters;
		}

		/**
		 * ABSTRACT
		 * overwrite this function to specify correct class
		 */
		protected function getClass():Class {
			return null;
		}
		
		/**
		 * ABSTRACT
		 * returns true when the filter should be applied. that means for example if 
		 * the blurfilter has blurX, blurY = 0 it shouldnt applied
		 */
		protected function shouldBeApplied():Boolean {
			return true;
		}
		
		/**
		 * ABSTRACT
		 * returns the default filter when no one is applied
		 */
		protected function defaultFilter():BitmapFilter {
			return null;
		}
		
		/**
		 * tweens the properties of the filter.
		 * @see ch.sfug.anim.tween.property.PropertyTween
		 */
		public function tweenFilter( obj:Object ):void {
			readStartFilter();
			PropertyTween( tween ).tween( obj );
		}
		
		/**
		 * returns the displayobject where the filter is applied on
		 */
		public function get target():DisplayObject {
			return t;
		}
		
		public function set target( trg:DisplayObject ):void {
			this.t = trg;
		}
		
		/**
		 * returns the filter instance that is tweened
		 */
		public function get filter():BitmapFilter {
			return BitmapFilter( tween.target );
		}
		
		public function set filter( f:BitmapFilter ):void {
			tween.target = f;
		}
	}
}
